// Fill out your copyright notice in the Description page of Project Settings.

#include "NVIDIAGfeSDKPrivatePCH.h"
#include "HighLightBlueprint.h"
#include "FNVIDIAGfeSDK.h"
#include "NVIDIAGfeSDKTypes.h"
#include "Platform.h"

#include <gfesdk/bindings/cpp/sdk_types_cpp.h>
#include <sdk_types_ipc.h>

template<typename TEnum>
static FORCEINLINE FString EnumToString(const FString& Name, TEnum Value)
{
	const UEnum* enumPtr = FindObject<UEnum>(ANY_PACKAGE, *Name, true);
	if (!enumPtr)
	{
		return FString("Invalid");
	}
	return enumPtr->GetNameByValue((int64)Value).ToString();
}

class CGFEHighlights
{
public:


	CGFEHighlights(FString AppName)
	{
		static const EGfeSDKScope kRequiredScopes[] = {
			EGfeSDKScope::Highlights,
			EGfeSDKScope::HighlightsRecordScreenshot,
			EGfeSDKScope::HighlightsRecordVideo
		};

		INVIDIAGfeSDK::Get().SetFileLogLevel(ELogVerbosity::Verbose);
		INVIDIAGfeSDK::Get().SetUnrealLogLevel(ELogVerbosity::Display);

		INVIDIAGfeSDK::Get().PermissionsChangedDelegate.BindRaw(this, &CGFEHighlights::OnPermissionsChanged);

		FGfeSDKCreateInputParams InParams;
		InParams.AppName = *AppName;
		InParams.RequiredScopes.Append(kRequiredScopes, sizeof(kRequiredScopes) / sizeof(EGfeSDKScope));
		InParams.PollForCallbacks = true;

		FGfeSDKCreateResponse OutParams;
		EGfeSDKReturnCode ret = INVIDIAGfeSDK::Get().Create(InParams, OutParams);
		if (ret == EGfeSDKReturnCode::Success)
		{
			// We have successfully initialized the SDK and passed the version check
		}
		else if (ret == EGfeSDKReturnCode::SuccessIpcOldSdk)
		{
			// We have successfully initialized the SDK. We are running an older version of the GFESDK
			// as compared to the installed GFE, but are still ok
			UE_LOG(LogTemp, Log, TEXT("We are running an older version of the GFESDK. Backend Version %d.%d GFE version %s"),
				OutParams.VersionMajor, OutParams.VersionMinor, *OutParams.NVIDIAGfeVersion);
		}
		else if (ret == EGfeSDKReturnCode::SuccessIpcOldGfe)
		{
			// We have successfully initialized the SDK, but the installed version of GFE is older.
			// Older functionality will still work, but game should check the returned Version to
			// see if the required functionality is present in the older version.
			UE_LOG(LogTemp, Log, TEXT("We have successfully initialized the SDK, but the installed version of GFE is older. Backend Version %d.%d GFE version %s"),
				OutParams.VersionMajor, OutParams.VersionMinor, *OutParams.NVIDIAGfeVersion);
		}
		else if (ret == EGfeSDKReturnCode::ErrorGfeVersion)
		{
			// The installed GFE is too old to continue. User must download newer GFE.
			UE_LOG(LogTemp, Warning, TEXT("The installed GFE is too old to continue. User must download newer GFE."));
		}
		else if (ret == EGfeSDKReturnCode::ErrorSdkVersion)
		{
			// This version of the GfeSDK is too old to continue. Game needs to distribute newer version.
			// This is UNLIKELY
			UE_LOG(LogTemp, Warning, TEXT("This version of the GfeSDK is too old to continue. Game needs to distribute newer version."));
		}
		else if (ret == EGfeSDKReturnCode::Error)
		{
			UE_LOG(LogTemp, Warning, TEXT("Failed to connect to GfeSDK backend"));
			return;
		}

		if (ret >= EGfeSDKReturnCode::Error)
		{
			UE_LOG(LogTemp, Log, TEXT("FAILED to connect with GfeSDK. Backend Version %d.%d GFE version %s"),
				OutParams.VersionMajor, OutParams.VersionMinor, *OutParams.NVIDIAGfeVersion);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Connected with GfeSDK. Backend Version %d.%d GFE version %s"),
				OutParams.VersionMajor, OutParams.VersionMinor, *OutParams.NVIDIAGfeVersion);
		}

		mPermissionsNeeded.Empty();
		for (auto& ScopePermission : OutParams.ScopePermissions)
		{
			UE_LOG(LogTemp, Log, TEXT("Required Scope %s has permission %s"),
				*EnumToString("EGfeSDKScope", ScopePermission.Key), *EnumToString("EGfeSDKPermission", ScopePermission.Value));
			if (ScopePermission.Value == EGfeSDKPermission::MustAsk)
			{
				mPermissionsNeeded.Add(ScopePermission.Key);
			}
		}
	}
	~CGFEHighlights()
	{
		INVIDIAGfeSDK::Get().Release();
	}	
protected:
	TMap<EGfeSDKScope, EGfeSDKPermission> mLastScopePermissions;
	TArray<EGfeSDKScope> mPermissionsNeeded;

	void OnPermissionsChanged(FGfeSDKPermissionsChangedData const& PermissionsChangedData)
	{
		UE_LOG(LogTemp, Log, TEXT("Permissions Changed notification"));
		mLastScopePermissions.Empty();
		for (auto& ScopePermission : PermissionsChangedData.ScopePermissions)
		{
			UE_LOG(LogTemp, Log, TEXT("Scope %s now has permission %s"),
				*EnumToString("EGfeSDKScope", ScopePermission.Key), *EnumToString("EGfeSDKPermission", ScopePermission.Value));
			if (ScopePermission.Value == EGfeSDKPermission::MustAsk)
			{
				mPermissionsNeeded.Add(ScopePermission.Key);
			}
			mLastScopePermissions.Add(ScopePermission.Key, ScopePermission.Value);
		}
	}
};



//---------------------------------------------------------------------------

inline EGfeSDKReturnCode ConvertRetCode(GfeSDK::NVGSDK_RetCode rt)
{
	switch (rt)
	{
	case GfeSDK::NVGSDK_SUCCESS: return EGfeSDKReturnCode::Success;
	case GfeSDK::NVGSDK_SUCCESS_VERSION_OLD_SDK: return EGfeSDKReturnCode::SuccessIpcOldSdk;
	case GfeSDK::NVGSDK_SUCCESS_VERSION_OLD_GFE: return EGfeSDKReturnCode::SuccessIpcOldGfe;
	case GfeSDK::NVGSDK_ERR_GFE_VERSION: return EGfeSDKReturnCode::ErrorGfeVersion;
	case GfeSDK::NVGSDK_ERR_SDK_VERSION: return EGfeSDKReturnCode::ErrorSdkVersion;
	case GfeSDK::NVGSDK_ERR_MODULE_NOT_LOADED: return EGfeSDKReturnCode::ErrorModuleNotLoaded;
	default: return EGfeSDKReturnCode::Error;
	}
}

//---------------------------------------------------------------------------
//--------- Polling from function library -----------------------------------
//---------------------------------------------------------------------------

UHighlightsFunctionLibrary::UHighlightsFunctionLibrary(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
}

//---------------------------------------------------------------------------

void UHighlightsFunctionLibrary::Poll()
{	
	FGfeSDKHighlights* HiL = INVIDIAGfeSDK::Get().Highlights();
	if (HiL)
	{
		HiL->Poll();
	}
}

void UHighlightsFunctionLibrary::ChekIfHighlightsAvailable(const FGfeSDKCreateResponse& InitProperties, bool &VideoGranted, bool &ScreenshotsGranted, EGfeSDKPermission &Video, EGfeSDKPermission &Screenshots)
{
	const EGfeSDKPermission* H = nullptr;
	const EGfeSDKPermission* V = nullptr;
	const EGfeSDKPermission* S = nullptr;
	for (auto & Pair : InitProperties.ScopePermissions)
	{
		switch (Pair.Key)
		{
		case EGfeSDKScope::Highlights:
			H = &Pair.Value;
			break;
		case EGfeSDKScope::HighlightsRecordVideo:
			V = &Pair.Value;
			break;
		case EGfeSDKScope::HighlightsRecordScreenshot:
			S = &Pair.Value;
			break;
		default:
			break;
		}
	}
	
	VideoGranted = false;
	ScreenshotsGranted = false;
	Video = EGfeSDKPermission::Denied;
	Screenshots = EGfeSDKPermission::Denied;

	if (H && (*H) == EGfeSDKPermission::Granted)
	{
		if (V)
		{
			Video = (*V);
			if (Video == EGfeSDKPermission::Granted)
				VideoGranted = true;
		}
		if (S)
		{
			Screenshots = (*S);
			if (Screenshots == EGfeSDKPermission::Granted)
				ScreenshotsGranted = true;
		}
	}
}

//---------------------------------------------------------------------------
//----------- Initialization class event ------------------------------------
//---------------------------------------------------------------------------

UInitHighlights* UInitHighlights::InitHighlights(UObject* WorldContextObject, const FString InGameName, const bool Video, const bool Screenshots)
{
	UInitHighlights* Proxy = NewObject<UInitHighlights>();
	Proxy->GameName = InGameName;
	Proxy->RequestedPermissions.Empty();
	Proxy->RequestedPermissions.Add(EGfeSDKScope::Highlights);
	if (Video)
		Proxy->RequestedPermissions.Add(EGfeSDKScope::HighlightsRecordVideo);
	if (Screenshots)
		Proxy->RequestedPermissions.Add(EGfeSDKScope::HighlightsRecordScreenshot);

	Proxy->WorldContextObject = WorldContextObject;
	return Proxy;
}

//---------------------------------------------------------------------------

void UInitHighlights::Activate()
{
	INVIDIAGfeSDK::Get().SetFileLogLevel(ELogVerbosity::Verbose);
	INVIDIAGfeSDK::Get().SetUnrealLogLevel(ELogVerbosity::Display);

	INVIDIAGfeSDK::Get().PermissionsChangedDelegate.BindUObject(this, &UInitHighlights::OnPermissionsChanged);

	FGfeSDKCreateInputParams InParams;
	InParams.AppName = *GameName;
	InParams.RequiredScopes = RequestedPermissions;
	InParams.PollForCallbacks = true;

	FGfeSDKCreateResponse OutParams;
	EGfeSDKReturnCode ret = INVIDIAGfeSDK::Get().Create(InParams, OutParams);
	if (ret == EGfeSDKReturnCode::Success)
	{
		// We have successfully initialized the SDK and passed the version check
	}
	else if (ret == EGfeSDKReturnCode::SuccessIpcOldSdk)
	{
		// We have successfully initialized the SDK. We are running an older version of the GFESDK
		// as compared to the installed GFE, but are still ok
		/*FFrame::KismetExecutionMessage(*FString::Printf(TEXT("We are running an older version of the GFESDK. Backend Version %d.%d GFE version %s"),
			OutParams.VersionMajor, OutParams.VersionMinor, *OutParams.NVIDIAGfeVersion), ELogVerbosity::Warning);*/
	}
	else if (ret == EGfeSDKReturnCode::SuccessIpcOldGfe)
	{
		// We have successfully initialized the SDK, but the installed version of GFE is older.
		// Older functionality will still work, but game should check the returned Version to
		// see if the required functionality is present in the older version.
		/*UE_LOG(LogTemp, Log, TEXT("We have successfully initialized the SDK, but the installed version of GFE is older. Backend Version %d.%d GFE version %s"),
			OutParams.VersionMajor, OutParams.VersionMinor, *OutParams.NVIDIAGfeVersion);*/
	}
	else if (ret == EGfeSDKReturnCode::ErrorGfeVersion)
	{
		// The installed GFE is too old to continue. User must download newer GFE.
		//UE_LOG(LogTemp, Warning, TEXT("The installed GFE is too old to continue. User must download newer GFE."));
		FFrame::KismetExecutionMessage(*FString::Printf(TEXT("The installed GFE is too old to continue. User must download newer GFE.")), ELogVerbosity::Error);
	}
	else if (ret == EGfeSDKReturnCode::ErrorSdkVersion)
	{
		// This version of the GfeSDK is too old to continue. Game needs to distribute newer version.
		// This is UNLIKELY
		FFrame::KismetExecutionMessage(*FString::Printf(TEXT("This version of the GfeSDK is too old to continue. Game needs to distribute newer version.")), ELogVerbosity::Error);
	}
	else if (ret == EGfeSDKReturnCode::Error)
	{
		//UE_LOG(LogTemp, Warning, TEXT("Failed to connect to GfeSDK backend"));
		return;
	}

	mPermissionsNeeded.Empty();
	for (auto& ScopePermission : OutParams.ScopePermissions)
	{
		/*UE_LOG(LogTemp, Log, TEXT("Required Scope %s has permission %s"),
			*EnumToString("EGfeSDKScope", ScopePermission.Key), *EnumToString("EGfeSDKPermission", ScopePermission.Value));*/
		if (ScopePermission.Value == EGfeSDKPermission::MustAsk)
		{
			mPermissionsNeeded.Add(ScopePermission.Key);
		}
	}

	if (ret >= EGfeSDKReturnCode::Error)
	{
		OnFailure.Broadcast(ret);
		UE_LOG(LogTemp, Log, TEXT("FAILED to connect with GfeSDK. Backend Version %d.%d GFE version %s"),
			OutParams.VersionMajor, OutParams.VersionMinor, *OutParams.NVIDIAGfeVersion);
	}
	else
	{
		OnSuccess.Broadcast(ret, OutParams);
		UE_LOG(LogTemp, Log, TEXT("Connected with GfeSDK. Backend Version %d.%d GFE version %s"),
			OutParams.VersionMajor, OutParams.VersionMinor, *OutParams.NVIDIAGfeVersion);
	}
}

//---------------------------------------------------------------------------

void UInitHighlights::Callback()
{

}

//---------------------------------------------------------------------------

void UInitHighlights::OnPermissionsChanged(FGfeSDKPermissionsChangedData const& PermissionsChangedData)
{
	UE_LOG(LogTemp, Log, TEXT("Permissions Changed notification"));
	mLastScopePermissions.Empty();
	for (auto& ScopePermission : PermissionsChangedData.ScopePermissions)
	{
		UE_LOG(LogTemp, Log, TEXT("Scope %s now has permission %s"),
			*EnumToString("EGfeSDKScope", ScopePermission.Key), *EnumToString("EGfeSDKPermission", ScopePermission.Value));
		if (ScopePermission.Value == EGfeSDKPermission::MustAsk)
		{
			mPermissionsNeeded.Add(ScopePermission.Key);
		}
		mLastScopePermissions.Add(ScopePermission.Key, ScopePermission.Value);
	}
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------


UHighlightsConfigureAsync* UHighlightsConfigureAsync::HighlightsConfigure(UObject* WorldContextObject, const FGfeSDKHighlightConfigParams& ConfigParams)
{
	UHighlightsConfigureAsync* Proxy = NewObject<UHighlightsConfigureAsync>();
	Proxy->WorldContextObject = WorldContextObject;
	Proxy->ConfigParams = ConfigParams;
	return Proxy;
}

//---------------------------------------------------------------------------

void __stdcall UHighlightsConfigureAsync::OnConfigureCallback(GfeSDK::NVGSDK_RetCode rt, void* context)
{
	UHighlightsConfigureAsync* Th = static_cast<UHighlightsConfigureAsync*>(context);
	if (Th)
	{
		if (NVGSDK_SUCCEEDED(rt))
		{
			Th->OnSuccess.Broadcast(ConvertRetCode(rt));
		}
		else
		{
			Th->OnFailure.Broadcast(ConvertRetCode(rt));
		}
		
	}

}
void UHighlightsConfigureAsync::Activate()
{
	FGfeSDKHighlights* HiL = INVIDIAGfeSDK::Get().Highlights();
	if (HiL)
	{
		HiL->ConfigureAsync(ConfigParams, &OnConfigureCallback, this);
	}
	else
	{
		OnFailure.Broadcast(EGfeSDKReturnCode::ErrorModuleNotLoaded);
	}
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------


UHighlightsOpenGroupAsync* UHighlightsOpenGroupAsync::HighlightsOpenGroup(UObject* WorldContextObject, const FGfeSDKHighlightOpenGroupParams& Params)
{
	UHighlightsOpenGroupAsync* Proxy = NewObject<UHighlightsOpenGroupAsync>();
	Proxy->WorldContextObject = WorldContextObject;
	Proxy->Params = Params;
	return Proxy;
}

//---------------------------------------------------------------------------

void __stdcall UHighlightsOpenGroupAsync::OnOpenGroupCallback(GfeSDK::NVGSDK_RetCode rt, void* context)
{
	UHighlightsOpenGroupAsync* Th = static_cast<UHighlightsOpenGroupAsync*>(context);
	if (Th)
	{
		if (NVGSDK_SUCCEEDED(rt))
		{
			Th->OnSuccess.Broadcast(ConvertRetCode(rt));
		}
		else
		{
			Th->OnFailure.Broadcast(ConvertRetCode(rt));
		}

	}

}
void UHighlightsOpenGroupAsync::Activate()
{
	FGfeSDKHighlights* HiL = INVIDIAGfeSDK::Get().Highlights();
	if (HiL)
	{
		HiL->OpenGroupAsync(Params, &OnOpenGroupCallback, this);
	}
	else
	{
		OnFailure.Broadcast(EGfeSDKReturnCode::ErrorModuleNotLoaded);
	}
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------


UHighlightsCloseGroupAsync* UHighlightsCloseGroupAsync::HighlightsCloseGroup(UObject* WorldContextObject, const FString& GroupId, const bool& DestroyHighlights)
{
	UHighlightsCloseGroupAsync* Proxy = NewObject<UHighlightsCloseGroupAsync>();
	Proxy->WorldContextObject = WorldContextObject;
	Proxy->Params.GroupId = GroupId;
	Proxy->Params.DestroyHighlights = DestroyHighlights;
	return Proxy;
}

//---------------------------------------------------------------------------

void __stdcall UHighlightsCloseGroupAsync::OnCloseGroupCallback(GfeSDK::NVGSDK_RetCode rt, void* context)
{
	UHighlightsCloseGroupAsync* Th = static_cast<UHighlightsCloseGroupAsync*>(context);
	if (Th)
	{
		if (NVGSDK_SUCCEEDED(rt))
		{
			Th->OnSuccess.Broadcast(ConvertRetCode(rt));
		}
		else
		{
			Th->OnFailure.Broadcast(ConvertRetCode(rt));
		}

	}

}
void UHighlightsCloseGroupAsync::Activate()
{
	FGfeSDKHighlights* HiL = INVIDIAGfeSDK::Get().Highlights();
	if (HiL)
	{
		HiL->CloseGroupAsync(Params, &OnCloseGroupCallback, this);
	}
	else
	{
		OnFailure.Broadcast(EGfeSDKReturnCode::ErrorModuleNotLoaded);
	}
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------


UHighlightsSetScreenshotAsync* UHighlightsSetScreenshotAsync::HighlightsSetScreenshot(UObject* WorldContextObject, const FString& GroupId, const FString& HighlightId)
{
	UHighlightsSetScreenshotAsync* Proxy = NewObject<UHighlightsSetScreenshotAsync>();
	Proxy->WorldContextObject = WorldContextObject;
	Proxy->Params.GroupId = GroupId;
	Proxy->Params.HighlightId = HighlightId;
	return Proxy;
}

//---------------------------------------------------------------------------

void __stdcall UHighlightsSetScreenshotAsync::OnSetScreenshotCallback(GfeSDK::NVGSDK_RetCode rt, void* context)
{
	UHighlightsSetScreenshotAsync* Th = static_cast<UHighlightsSetScreenshotAsync*>(context);
	if (Th)
	{
		if (NVGSDK_SUCCEEDED(rt))
		{
			Th->OnSuccess.Broadcast(ConvertRetCode(rt));
		}
		else
		{
			Th->OnFailure.Broadcast(ConvertRetCode(rt));
		}

	}

}
void UHighlightsSetScreenshotAsync::Activate()
{
	FGfeSDKHighlights* HiL = INVIDIAGfeSDK::Get().Highlights();
	if (HiL)
	{
		HiL->SetScreenshotHighlightAsync(Params, &OnSetScreenshotCallback, this);
	}
	else
	{
		OnFailure.Broadcast(EGfeSDKReturnCode::ErrorModuleNotLoaded);
	}
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------


UHighlightsSetVideoAsync* UHighlightsSetVideoAsync::HighlightsSetVideo(UObject* WorldContextObject, const FString& GroupId, const FString& HighlightId, const int32& StartDelta, const int32& EndDelta)
{
	UHighlightsSetVideoAsync* Proxy = NewObject<UHighlightsSetVideoAsync>();
	Proxy->WorldContextObject = WorldContextObject;
	Proxy->Params.GroupId = GroupId;
	Proxy->Params.HighlightId = HighlightId;
	Proxy->Params.StartDelta = StartDelta;
	Proxy->Params.EndDelta = EndDelta;
	return Proxy;
}

//---------------------------------------------------------------------------

void __stdcall UHighlightsSetVideoAsync::OnSetVideoCallback(GfeSDK::NVGSDK_RetCode rt, void* context)
{
	UHighlightsSetVideoAsync* Th = static_cast<UHighlightsSetVideoAsync*>(context);
	if (Th)
	{
		if (NVGSDK_SUCCEEDED(rt))
		{
			Th->OnSuccess.Broadcast(ConvertRetCode(rt));
		}
		else
		{
			Th->OnFailure.Broadcast(ConvertRetCode(rt));
		}

	}

}
void UHighlightsSetVideoAsync::Activate()
{
	FGfeSDKHighlights* HiL = INVIDIAGfeSDK::Get().Highlights();
	if (HiL)
	{
		if (Params.EndDelta <= Params.StartDelta)
		{
			OnFailure.Broadcast(EGfeSDKReturnCode::ErrorWrongTimeRangeSet);
		}
		else
		{
			HiL->SetVideoHighlightAsync(Params, &OnSetVideoCallback, this);
		}
	}
	else
	{
		OnFailure.Broadcast(EGfeSDKReturnCode::ErrorModuleNotLoaded);
	}
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------


UHighlightsSummaryAsync* UHighlightsSummaryAsync::HighlightsOpenSummary(UObject* WorldContextObject, const FGfeSDKHighlightSummaryParams& Params)
{
	UHighlightsSummaryAsync* Proxy = NewObject<UHighlightsSummaryAsync>();
	Proxy->WorldContextObject = WorldContextObject;
	Proxy->Params = Params;
	return Proxy;
}

//---------------------------------------------------------------------------

void __stdcall UHighlightsSummaryAsync::OnOpenSummaryCallback(GfeSDK::NVGSDK_RetCode rt, void* context)
{
	UHighlightsSummaryAsync* Th = static_cast<UHighlightsSummaryAsync*>(context);
	if (Th)
	{
		if (NVGSDK_SUCCEEDED(rt))
		{
			Th->OnSuccess.Broadcast(ConvertRetCode(rt));
		}
		else
		{
			Th->OnFailure.Broadcast(ConvertRetCode(rt));
		}

	}

}
void UHighlightsSummaryAsync::Activate()
{
	FGfeSDKHighlights* HiL = INVIDIAGfeSDK::Get().Highlights();
	if (HiL)
	{
		HiL->OpenSummaryAsync(Params, &OnOpenSummaryCallback, this);
	}
	else
	{
		OnFailure.Broadcast(EGfeSDKReturnCode::ErrorModuleNotLoaded);
	}
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------


UHighlightsGetNumberAsync* UHighlightsGetNumberAsync::HighlightsGetNumberOfHighlights(UObject* WorldContextObject, const FString& GroupID, const EGfeSDKHighlightType& TagFilter, const EGfeSDKHighlightSignificance& SignificanceFilter)
{
	UHighlightsGetNumberAsync* Proxy = NewObject<UHighlightsGetNumberAsync>();
	Proxy->WorldContextObject = WorldContextObject;
	Proxy->Params.GroupId = GroupID;
	Proxy->Params.TagsFilter = TagFilter;
	Proxy->Params.SignificanceFilter = SignificanceFilter;
	return Proxy;
}

//---------------------------------------------------------------------------

void __stdcall UHighlightsGetNumberAsync::OnGetNumberCallback(GfeSDK::NVGSDK_RetCode rt, GfeSDK::NVGSDK_Highlights_NumberOfHighlights const* NumberOfHighlights, void* context)
{
	UHighlightsGetNumberAsync* Th = static_cast<UHighlightsGetNumberAsync*>(context);
	if (Th)
	{
		if (NVGSDK_SUCCEEDED(rt))
		{
			Th->OnSuccess.Broadcast(ConvertRetCode(rt), NumberOfHighlights->numberOfHighlights);
		}
		else
		{
			Th->OnFailure.Broadcast(ConvertRetCode(rt));
		}

	}

}
void UHighlightsGetNumberAsync::Activate()
{
	FGfeSDKHighlights* HiL = INVIDIAGfeSDK::Get().Highlights();
	if (HiL)
	{
		HiL->GetNumberOfHighlightsAsync(Params, &OnGetNumberCallback, this);
	}
	else
	{
		OnFailure.Broadcast(EGfeSDKReturnCode::ErrorModuleNotLoaded);
	}
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------


URequestPermissionsAsync* URequestPermissionsAsync::GFERequestPermissions(UObject* WorldContextObject, const bool Video, const bool Screenshots)
{
	URequestPermissionsAsync* Proxy = NewObject<URequestPermissionsAsync>();
	Proxy->WorldContextObject = WorldContextObject;

	Proxy->Params.Scopes.Empty();
	Proxy->Params.Scopes.Add(EGfeSDKScope::Highlights);
	if (Video)
		Proxy->Params.Scopes.Add(EGfeSDKScope::HighlightsRecordVideo);
	if (Screenshots)
		Proxy->Params.Scopes.Add(EGfeSDKScope::HighlightsRecordScreenshot);
	return Proxy;
}

//---------------------------------------------------------------------------

void __stdcall URequestPermissionsAsync::OnGetNumberCallback(GfeSDK::NVGSDK_RetCode rt, void* context)
{
	URequestPermissionsAsync* Th = static_cast<URequestPermissionsAsync*>(context);
	if (Th)
	{
		if (NVGSDK_SUCCEEDED(rt))
		{
			Th->OnSuccess.Broadcast(ConvertRetCode(rt));
		}
		else
		{
			Th->OnFailure.Broadcast(ConvertRetCode(rt));
		}

	}

}
void URequestPermissionsAsync::Activate()
{
	FGfeSDKCore* Core = INVIDIAGfeSDK::Get().Core();
	if (Core)
	{
		Core->RequestPermissionsAsync(Params, &OnGetNumberCallback, this);
	}
	else
	{
		OnFailure.Broadcast(EGfeSDKReturnCode::ErrorModuleNotLoaded);
	}
}
